package com.xyy.ec.qualification.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.xyy.ec.qualification.config.ConfigManagerService;
import com.xyy.ec.qualification.enums.TaskEnum;
import com.xyy.ec.qualification.exception.ServiceException;
import com.xyy.ec.qualification.executor.db.DbSqlManager;
import com.xyy.ec.qualification.pojo.QueryParamDto;
import com.xyy.ec.qualification.pojo.SellerDataConfig;
import com.xyy.ec.qualification.pojo.ServiceResultDto;
import com.xyy.ec.qualification.utils.MD5Util;
import com.xyy.ec.qualification.utils.http.RedirectUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 数据同步服务
 */
@Service
@Slf4j
public abstract class DataSyncServiceHandel {
    @Resource
    private Environment env;
    @Value("${h.api.host}")
    private String hApiHost;

    @Value("${h.upload.file.url}")
    private String url;

    public String getUploadUrl(){
        return url;
    }

    /**
     * 执行活动类型
     *
     * @param taskEnum
     * @return
     */
    public void syncErpDataToPop(TaskEnum taskEnum) {
        try {
            //1.获取数据库执行器
            //获取执行的数据库类型
            String dbType = null == ConfigManagerService.getDatasourceConfig() ? "" : ConfigManagerService.getDatasourceConfig().getDbTypeName();

            if (StringUtils.isEmpty(dbType)) {
                log.error("#配置错误,dbType未配置，任务名称:{}", taskEnum.getTaskName() + taskEnum.getTaskId());
                throw new ServiceException("配置错误,dbType未配置");
            }

            //2.获取查询条件
            List<String> erpCodes = queryFilterInfoGet(taskEnum.getTaskId());
            if (CollectionUtils.isEmpty(erpCodes)) {
                log.info("#没有要同步的商品编码:erpCodes{}", taskEnum.getTaskName() + taskEnum.getTaskId());
                return;
            }

            List<List<String>> lists = Lists.partition(erpCodes, 200);
            List<Map<String, Object>> serverResultList = null;
            for (List<String> list : lists) {
                String sql = DbSqlManager.genSQL(taskEnum.getSql(), taskEnum.getQueryField(), list);
                serverResultList = DbSqlManager.quereyData(sql, null);
                if(CollectionUtils.isEmpty(serverResultList)){
                    continue;
                }
                List<Map<String, Object>> newServerResultList = fileConvert2Url(taskEnum, serverResultList);
                if(CollectionUtils.isEmpty(newServerResultList)){
                    continue;
                }
                syncErpDataToPopProcess(taskEnum.getTaskId(), newServerResultList);
            }
        } catch (ServiceException e) {
            log.error("#syncErpDataToPop上传执行异常,task={},e={}", taskEnum.getTaskId(), e);
        } catch (InterruptedException e) {
            log.error("#syncErpDataToPop执行休眠中断,task={},e={}", taskEnum.getTaskId(), e);
        }
    }

    public abstract List<Map<String, Object>> fileConvert2Url(TaskEnum taskEnum, List<Map<String, Object>> serverResultList);


    private void syncErpDataToPopProcess(Integer taskId, List<Map<String, Object>> resultList) throws InterruptedException {

        List<Map<String, Object>> serverResultList = transferServerKey(resultList);
        //3.同步
        boolean reulst = uploadData(taskId, serverResultList);
    }


    private boolean uploadData(Integer taskId, List<Map<String, Object>> serverResultList) {
        String url = hApiHost + env.getProperty("task.url.taskDataPush");
        boolean relustFlag;
        Map<String, Object> data = Maps.newHashMap();
        data.put("appId", SellerDataConfig.appId);
        data.put("orgId", SellerDataConfig.orgId);
        data.put("taskId", taskId);
        data.put("jsonData", JSONObject.toJSONString(serverResultList));
        data.put("sign", MD5Util.encrypt(data, SellerDataConfig.appSecret));
        String result = RedirectUtil.doPostByJson(url,
                JSONObject.toJSONString(data, SerializerFeature.WriteDateUseDateFormat));
        ServiceResultDto serviceResultDto = JSONObject.parseObject(result, ServiceResultDto.class);
        if (Objects.isNull(serviceResultDto) || !serviceResultDto.isSuccess() || StringUtils.isEmpty(serviceResultDto.getData())) {
            log.error("#uploadData上报数据异常,taskId={},result={}", taskId, result);
            result = RedirectUtil.doPostByJson(url,
                    JSONObject.toJSONString(data, SerializerFeature.WriteDateUseDateFormat));
            serviceResultDto = JSONObject.parseObject(result, ServiceResultDto.class);
        }
        relustFlag = Objects.nonNull(serviceResultDto) && serviceResultDto.isSuccess() ? Boolean.TRUE : Boolean.FALSE;
        log.info("#uploadData上报数据成功,任务id：{},上报数据条数:{}", taskId, serverResultList.size());

        TaskEnum anEnum = TaskEnum.FactorEnumMap.get(taskId);
        if (relustFlag) {
            log.info("{} 任务执行成功，上报数据{}条。", anEnum.getTaskName(), serverResultList.size());
        } else {
            log.info("{} 任务执行失败了！！！", anEnum.getTaskName());
        }
        return relustFlag;
    }

    private static List<Map<String, Object>> transferServerKey(List<Map<String, Object>> resultList) {
        List<Map<String, Object>> serverResultList = Lists.newArrayList();
        for (Map<String, Object> subMap : resultList) {
            if (subMap == null || subMap.isEmpty()) {
                log.warn("DataSyncServiceHandel.transferServerKey#subMap:{}", JSON.toJSONString(subMap));
                continue;
            }
            Map<String, Object> tempMap = Maps.newHashMap();
            for (Map.Entry<String, Object> entry : subMap.entrySet()) {
                if (entry.getValue() instanceof String) {
                    //如果是字符串，去掉两边空格
                    tempMap.put(entry.getKey(), ((String) entry.getValue()).trim());
                } else {
                    tempMap.put(entry.getKey(), entry.getValue());
                }
            }
            serverResultList.add(tempMap);
        }
        return serverResultList;
    }

    /**
     * 获取查询条件信息
     *
     * @param taskId
     * @return
     */
    private List<String> queryFilterInfoGet(Integer taskId) throws ServiceException {
        String url = hApiHost + env.getProperty("task.url.querySqlParam");
        Map<String, Object> paramMap = Maps.newHashMap();
        paramMap.put("appId", SellerDataConfig.appId);
        paramMap.put("orgId", SellerDataConfig.orgId);
        paramMap.put("taskId", taskId);
        String sign = MD5Util.encrypt(paramMap, SellerDataConfig.appSecret);
        paramMap.put("sign", sign);
        String result = RedirectUtil.doGetParam(url, paramMap);
        if (StringUtils.isEmpty(result)) {
            log.error("#queryFilterInfoGet 未获取到sql查询条件,paramMap={}", JSONObject.toJSONString(paramMap));
            throw new ServiceException("未获取到sql查询条件");
        }
        ServiceResultDto serviceResultDto = JSONObject.parseObject(result, ServiceResultDto.class);
        if (!serviceResultDto.isSuccess()) {
            log.error("#queryFilterInfoGet 查询SQL条件接口返回异常,taskId={},result={}", taskId, result);
            throw new ServiceException("sql查询条件接口返回异常," + serviceResultDto.getMsg());
        }
        if (StringUtils.isEmpty(serviceResultDto.getData())) {
            log.info("#queryFilterInfoGet无查询条件,查询结果为空");
            return null;
        }

        JSONObject jsonObjectResult = JSONObject.parseObject(serviceResultDto.getData());
        String dataJson = jsonObjectResult.getString("dataJson");
        if (StringUtils.isEmpty(dataJson)) {
            log.info("#queryFilterInfoGet无查询条件,dataJson为空");
            return null;
        }
        String resultSign = jsonObjectResult.getString("sign");
        boolean checkSign = StringUtils.isEmpty(dataJson) || StringUtils.isEmpty(resultSign)
                || resultSign.equals(MD5Util.encrypt(dataJson, SellerDataConfig.appSecret));
        if (!checkSign) {
            log.error("#queryFilterInfoGet查询条件签名校验异常,taskDto={},result={}", taskId, JSONObject.toJSONString(result));
            throw new ServiceException("queryFilterInfoGet查询条件签名校验异常");
        }
        QueryParamDto queryParamDto = JSONObject.parseObject(dataJson, QueryParamDto.class);
        return queryParamDto.getListQueryParam();
    }
}
